package com.eii.resubmit.aop.request;

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Controller;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

/**
 * @author eii
 * @time 2020/11/28 8:50 下午
 */
public class UAOP {

    /**
     * 判断该类是否为Controller
     */
    public static boolean isController(Class<?> klass) {
        if (AnnotationUtils.findAnnotation(klass, Controller.class) != null) {
            return true;
        }
        if (AnnotationUtils.findAnnotation(klass, RestController.class) != null) {
            return true;
        }
        return false;
    }

    /**
     * 判断方法返回类型是否为AsyncResult-即ListenableFuture(类型参数T为Result)<br>
     * 如果是AsyncResult,返回true.如果是Result,返回false.<br>
     * 如果既不是AsyncResult,也不是Result,则抛出异常.<br>
     * @see org.springframework.util.concurrent.ListenableFuture
     */
    public static boolean isAsyncResultAsReturn(Method method) {
        Type type = method.getAnnotatedReturnType().getType();
        if (isAsyncResult(type)) {
            return true;
        }
        if (isResult(type)) {
            return false;
        }
        return true;
//        if (!method.isAnnotationPresent(Check.class)) {
//            return false;
//        }
//        throw new RuntimeException("含有", "@", Check.class.getCanonicalName(), "注解的方法", UReflect.fullName(method),
//                "的返回值类型必须为",
//                ListenableFuture.class.getCanonicalName(), "或者", Value.class.getCanonicalName());
    }

    private static boolean isResult(Type type) {
        //todo 真实项目，请改为判断controller 接口实际返回类型
        //这里 测试用controller的返回值都是Map或者Map的泛型类 ,判断其返回值是否匹配
        if (type instanceof Class) {
            return Map.class.isAssignableFrom((Class<?>) type);
        }
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            return Map.class.isAssignableFrom((Class<?>) parameterizedType.getRawType());
        }
        return false;
    }

    private static boolean isAsyncResult(Type type) {
        if (!(type instanceof ParameterizedType)) {
            return false;
        }
        Type rawType = ((ParameterizedType) type).getRawType();
        if (!(rawType instanceof Class) || !ListenableFuture.class.isAssignableFrom((Class<?>) rawType)) {
            return false;
        }
        Type[] types = ((ParameterizedType) type).getActualTypeArguments();
        if (types == null || types.length == 0) {
            return false;
        }
        Type typeArgument = types[0];
        //todo 真实项目，请改为判断controller 接口实际返回类型
        //这里 测试用controller的返回值都是Map或者Map的泛型类 ,判断其返回值是否匹配
        if (typeArgument instanceof Class) {
            return Map.class.isAssignableFrom((Class<?>) typeArgument);
        }
        if (typeArgument instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) typeArgument;
            return Map.class.isAssignableFrom((Class<?>) parameterizedType.getRawType());
        }
        return false;
    }
}
